package ferp.android.activities.preferences;

import android.app.Dialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Bundle;
import android.preference.*;
import android.text.InputType;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import ferp.android.GUI;
import ferp.android.R;
import ferp.android.dialogs.*;
import ferp.android.managers.CloudManager;
import ferp.android.managers.DeckManager;
import ferp.android.managers.ProfileManager;
import ferp.android.tasks.center.TaskProfileCreate;
import ferp.android.tasks.local.TaskDeckLoader;
import ferp.core.game.Settings;
import ferp.core.player.Profile;

import java.util.Locale;

/**
 * User: olegs
 * Date: 29/03/12 21:10
 */
public class Preferences extends PreferenceActivity implements Preference.OnPreferenceChangeListener,
                                                               MessageDialog.Listener,
                                                               EditTextDialog.Listener,
                                                               RadioListViewDialog.Listener,
                                                               CheckListViewDialog.Listener,
                                                               AnimationTimeDialog.Listener,
                                                               TaskProfileCreate.Listener,
                                                               TaskDeckLoader.Listener
{
  public static final int REQUEST_CODE = 1;

  public static final class Intent
  {
    public static final String NEW_GAME = "new_game";
    public static final String ENTRANCE = "entrance";
  }

  public static String getDeviceID(Context context)
  {
    SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
    String id = sp.getString(DEVICE_ID, null);

    if (id == null)
    {
      SharedPreferences.Editor editor = sp.edit();

      id = java.util.UUID.randomUUID().toString();

      editor.putString(DEVICE_ID, id);
      editor.commit();
    }

    return id;
  }

  public static Resources setLocale(Context context, Profile profile)
  {
    // ensure we use the right context
    context = context.getApplicationContext();

    if (profile != null)
    {
      Locale locale = new Locale(profile.settings.locale.code());
      Configuration config = new Configuration(context.getResources().getConfiguration());

      Locale.setDefault(locale);
      config.locale = locale;
      context.getResources().updateConfiguration(config, null);
    }

    return context.getResources();
  }

  public <T> T find(Class<T> cls, int key)
  {
    return cls.cast(findPreference(String.valueOf(key)));
  }

  public void onBeforeProfileCreation()
  {
    showDialog(Dialogs.PROGRESS_PROFILE_UPDATING);
  }

  public void onAfterProfileCreation()
  {
    GUI.tryToDismissDialog(this, Dialogs.PROGRESS_PROFILE_UPDATING);

    try
    {
      // do not override existing snapshot here
      pm.saveCurrentProfile(false);

      finish();
    }
    catch (Exception e)
    {
      GUI.toast(this, getString(R.string.error_saving_profile));
    }
  }

  public void onBackPressed()
  {
    Profile p = pm.getCurrentProfile();

    if (p.nickname == null || p.nickname.length() == 0)
      showDialog(Dialogs.CLOSE_CONFIRMATION);
    else
      new TaskProfileCreate(this, p, this).execute();
  }

  public void onYesClick(int requestCode)
  {
    switch (requestCode)
    {
      case Dialogs.CLOSE_CONFIRMATION:
        // restore the original current profile stored in preferences
        pm.setCurrentProfile();
        finish();
        break;
    }
  }

  public void onNoClick(int requestCode)
  {
    switch (requestCode)
    {
      case Dialogs.INFORMATION_CLOUD_SAVE:
        // reset the cloud save setting to NONE here
        pm.getCurrentProfile().settings.cloudSave = find(List.class, Dialogs.CLOUD_SAVE).update(R.array.cloud_save_types, 2, Settings.CloudSave.class);
        break;
    }
  }

  public void onSaveClick(int requestCode, String value)
  {
    Profile p = pm.getCurrentProfile();
    EditText preference = find(EditText.class, requestCode);

    switch (requestCode)
    {
      case Dialogs.NICKNAME:
        if (value.length() < MIN_PLAYER_NAME_SIZE || value.length() > MAX_PLAYER_NAME_SIZE)
        {
          GUI.toast(this, getString(R.string.error_player_name, MIN_PLAYER_NAME_SIZE, MAX_PLAYER_NAME_SIZE));
          return;
        }

        p.nickname = value;
        preference.update(value, value);
        break;

      case Dialogs.POOL_SIZE:
        if (value.length() == 0)
        {
          GUI.toast(this, getString(R.string.error_pool_cannot_be_empty));
          return;
        }

        try
        {
          int poolSize = Integer.parseInt(value);
          if (poolSize < MIN_POOL_SIZE || poolSize > MAX_POOL_SIZE) //Profile.current.balance)
          {
            GUI.toast(this, getString(R.string.error_pool_size, MIN_POOL_SIZE, MAX_POOL_SIZE));
            return;
          }

          // For Rostov pool size must be even
          if (p.settings.isRostov() && poolSize %2 != 0)
          {
            GUI.toast(this, getString(R.string.error_pool_size_must_be_even));
            return;
          }

          p.settings.poolSize = Integer.parseInt(value);
          preference.update(value, value);
        }
        catch (NumberFormatException e)
        {
          GUI.toast(this, getString(R.string.error_pool_size, MIN_POOL_SIZE, MAX_POOL_SIZE));
          return;
        }
        break;
    }

    GUI.tryToDismissDialog(this, requestCode);
  }

  public void onItemSelected(int requestCode, int selected)
  {
    List preference = find(List.class, requestCode);
    Profile p = pm.getCurrentProfile();

    GUI.tryToDismissDialog(this, requestCode);

    switch (requestCode)
    {
      case Dialogs.LEVEL_PLAYER_LEFT:
        p.settings.levels[0] = preference.update(R.array.player_levels, selected, Settings.Level.class);
        break;

      case Dialogs.LEVEL_PLAYER_RIGHT:
        p.settings.levels[1] = preference.update(R.array.player_levels, selected, Settings.Level.class);
        break;

      case Dialogs.POOL_TYPE:
        // For Rostov pool size must be even
        if (selected == Settings.GameFlavor.ROSTOV.ordinal() && p.settings.poolSize % 2 != 0)
        {
          // assign previous preference value
          preference.update(getPoolTypesArray(p.settings), p.settings.gameFlavor.ordinal(), Settings.GameFlavor.class);

          GUI.toast(this, getString(R.string.error_pool_size_must_be_even));
          return;
        }

        p.settings.gameFlavor = preference.update(getPoolTypesArray(p.settings), selected, Settings.GameFlavor.class);
        // set correct default values for the game flavor
        setGameFlavorDefaults();
        break;

      case Dialogs.WHIST_TYPE:
        p.settings.whistType = preference.update(R.array.whist_types, selected, Settings.WhistType.class);
        break;

      case Dialogs.WHIST_ON_6_SPADES:
        p.settings.whistOn6Spades = preference.update(R.array.whist_on_6_spades_types, selected, Settings.WhistOn6Spades.class);
        break;

      case Dialogs.TRICKING_10:
        p.settings.tricking10 = preference.update(R.array.whist_tricking10_types, selected, Settings.Tricking10.class);
        break;

      case Dialogs.MISERE_MODE:
        p.settings.misereMode = preference.update(R.array.misere_modes, selected, Settings.MisereMode.class);
        break;

      case Dialogs.PASSING_TYPE:
        p.settings.passingType = preference.update(R.array.passing_types, selected, Settings.PassingType.class);
        break;

      case Dialogs.PASSING_PROGRESSION:
        p.settings.passingProgression = preference.update(R.array.passing_progressions, selected, Settings.PassingProgression.class);
        break;

      case Dialogs.PASSING_TRICK_COST:
        p.settings.passingTrickCost = preference.update(R.array.passing_trick_costs, selected, Settings.PassingTrickCost.class);
        break;

      case Dialogs.PASSING_EXIT:
        p.settings.passingExit = preference.update(R.array.passing_exits, selected, Settings.PassingExit.class);
        break;

      case Dialogs.SUIT_ORDER:
        p.settings.suitOrder = preference.update(R.array.suit_orders, selected, Settings.SuitOrder.class);
        break;

      case Dialogs.RANK_ORDER:
        p.settings.rankOrder = preference.update(R.array.rank_orders, selected, Settings.RankOrder.class);
        break;

      case Dialogs.LOCALE:
        p.settings.locale = preference.update(R.array.locale_types, selected, Settings.Locale.class);
        // set new locale
        setLocale(this, p);
        // reset screen to reflect locale change
        setup(p);
        break;

      case Dialogs.ORIENTATION:
        p.settings.orientation = preference.update(R.array.orientation_types, selected, Settings.Orientation.class);
        // set new orientation
        //GUI.setOrientation(this, p);
        // reset screen to reflect orientation change
        //setup(p);

        finish();
        startActivity(getIntent());

        break;

      case Dialogs.CONFIRM_BID:
        p.settings.confirmations.bid = preference.update(R.array.confirmation_types, selected, Settings.Confirmation.class);
        break;

      case Dialogs.CONFIRM_CONTRACT:
        p.settings.confirmations.contract = preference.update(R.array.confirmation_types, selected, Settings.Confirmation.class);
        break;

      case Dialogs.DECKS:
        TaskDeckLoader.execute(this, this, preference.getEntryValues()[selected].toString());
        break;

      case Dialogs.CLOUD_SAVE:
        p.settings.cloudSave = preference.update(R.array.cloud_save_types, selected, Settings.CloudSave.class);

        if (p.settings.cloudSave != Settings.CloudSave.NONE)
        {
          // warn the user about google authorization requirements for this feature
          if (!CloudManager.instance(this).isLoggedIn())
            showDialog(Dialogs.INFORMATION_CLOUD_SAVE);
        }

        break;

      case Dialogs.CARD_MOVING_MODE:
        p.settings.cardMovingMode = preference.update(R.array.card_moving_modes, selected, Settings.CardMovingMode.class);
        break;
    }
  }

  @Override
  public void onSaveClick(int requestCode, boolean[] choices)
  {
    Profile p = pm.getCurrentProfile();

    switch (requestCode)
    {
      case Dialogs.PASSING_INTERRUPT:
        // update preference
        List preference = find(List.class, requestCode);

        // copy new selected values
        System.arraycopy(choices, 0, p.settings.passingInterruptions, 0, choices.length);
        preference.update(p.settings.passingInterruptions, R.array.passing_interruptions, R.string.settings_passing_interrupt_successful_whisted_game);

        break;
    }

    GUI.tryToDismissDialog(this, requestCode);
  }

  @Override
  public void onSaveClick(int requestCode, long value)
  {
    Profile p = pm.getCurrentProfile();

    switch (requestCode)
    {
      case Dialogs.ANIMATION_TIME:
        EditText preference = find(EditText.class, requestCode);

        p.settings.animationTime = value;
        preference.update(String.valueOf(value), getAnimationTimeSummary(value));

        break;
    }

    GUI.tryToDismissDialog(this, requestCode);
  }

  public boolean onPreferenceChange(Preference preference, Object o)
  {
    Profile profile = pm.getCurrentProfile();
    Boolean value = (Boolean)o;

    switch (Integer.valueOf(preference.getKey()))
    {
      case Dialogs.USE_CENTER:
        profile.useCenter = value;
        break;

      case Dialogs.USE_ORIGINAL_GAME_TYPE_NAMES:
        profile.settings.useOriginalGameTypeNames = value;
        List.setup(this, Dialogs.POOL_TYPE, getPoolTypesArray(profile.settings), profile.settings.gameFlavor, Settings.GameFlavor.class, newGame);
        break;

      case Dialogs.SUIT_SPACING:
        profile.settings.suitSpacing = value;
        break;

      case Dialogs.ROUND_END_TAP_WHEN_NOT_PLAYING:
        profile.settings.roundEndTapWhenNotPlaying = value;
        break;

      case Dialogs.ROUND_END_TAP_WHEN_LAST_MOVER_ANDROID:
        profile.settings.roundEndTapWhenLastMoverAndroid = value;
        break;

      case Dialogs.ROUND_END_TAP_WHEN_LAST_MOVER_HUMAN:
        profile.settings.roundEndTapWhenLastMoverHuman = value;
        break;

      case Dialogs.AUTOMATE_OBVIOUS_MOVES:
        profile.settings.automateObviousMoves = value;
        break;

      case Dialogs.SKIP_GAME_ON_PASS:
        profile.settings.skipGameOnPass = value;
        break;

      case Dialogs.WITHOUT_3:
        profile.settings.without3 = value;
        break;
    }

    return true;
  }

  @Override
  public void onDeckLoadStart(String deck)
  {
    LoadingDialog.showDeck(this, deck);
  }

  @Override
  public void onDeckLoadFinished(DeckManager dm, String deck)
  {
    Profile profile = ProfileManager.regular(this).getCurrentProfile();
    DeckList preference = find(DeckList.class, Dialogs.DECKS);
    String error = dm.error(this, deck);

    LoadingDialog.dismiss();

    if (error == null)
      profile.settings.deck = preference.update(preference.findIndexOfValue(deck));
    else
      GUI.toast(this, error);
  }

  @Override
  protected void onCreate(Bundle savedInstanceState)
  {
    // initialize profile manager if needed
    pm = ProfileManager.regular(getApplication());
    Profile profile = pm.getCurrentProfile();

    // set correct orientation depending on device
    GUI.setOrientation(this, profile);

    super.onCreate(savedInstanceState);

    if (profile == null)
      finish();
    else
    {
      // fixes background image problem on tablets
      clearBackground(findViewById(android.R.id.content));

      setLocale(this, profile);

      // is it a new game ?
      newGame = getIntent().getExtras().getBoolean(Intent.NEW_GAME);
      entrance = getIntent().getExtras().getBoolean(Intent.ENTRANCE);

      // setup preference screen
      setup(profile);

      // show player name dialog in case the name is empty
      if (profile.nickname == null)
        showDialog(Dialogs.NICKNAME);
    }
  }

  @Override
  protected Dialog onCreateDialog(int id)
  {
    switch (id)
    {
      case Dialogs.PROGRESS_PROFILE_UPDATING:
        return new ProgressDialog(this);

      case Dialogs.NICKNAME:
      case Dialogs.POOL_SIZE:
        return new EditTextDialog(this, this, id);

      case Dialogs.LEVEL_PLAYER_LEFT:
      case Dialogs.LEVEL_PLAYER_RIGHT:
      case Dialogs.POOL_TYPE:
      case Dialogs.PASSING_TYPE:
      case Dialogs.PASSING_PROGRESSION:
      case Dialogs.PASSING_TRICK_COST:
      case Dialogs.PASSING_EXIT:
      case Dialogs.WHIST_TYPE:
      case Dialogs.WHIST_ON_6_SPADES:
      case Dialogs.TRICKING_10:
      case Dialogs.MISERE_MODE:
      case Dialogs.SUIT_ORDER:
      case Dialogs.RANK_ORDER:
      case Dialogs.LOCALE:
      case Dialogs.ORIENTATION:
      case Dialogs.CONFIRM_BID:
      case Dialogs.CONFIRM_CONTRACT:
      case Dialogs.CLOUD_SAVE:
      case Dialogs.CARD_MOVING_MODE:
        return new RadioListViewDialog(this, this, id);

      case Dialogs.DECKS:
        return new DecksDialog(this, this, id);

      case Dialogs.PASSING_INTERRUPT:
        return new CheckListViewDialog(this, this, id);

      case Dialogs.CLOSE_CONFIRMATION:
      case Dialogs.INFORMATION_CLOUD_SAVE:
        return new MessageDialog(this, this, id);

      case Dialogs.ANIMATION_TIME:
        return new AnimationTimeDialog(this, this, id);
    }

    return super.onCreateDialog(id);
  }

  @Override
  protected void onPrepareDialog(int id, Dialog dialog)
  {
    Profile profile = pm.getCurrentProfile();

    setLocale(this, profile);

    super.onPrepareDialog(id, dialog);

    switch (id)
    {
      case Dialogs.NICKNAME:
      case Dialogs.POOL_SIZE:
      {
        EditTextPreference preference = find(EditTextPreference.class, id);

        ((EditTextDialog)dialog).set(preference.getDialogTitle().toString(), preference.getText(), preference.getEditText().getInputType());
        break;
      }

      case Dialogs.LEVEL_PLAYER_LEFT:
      case Dialogs.LEVEL_PLAYER_RIGHT:
      case Dialogs.POOL_TYPE:
      case Dialogs.PASSING_TYPE:
      case Dialogs.PASSING_PROGRESSION:
      case Dialogs.PASSING_TRICK_COST:
      case Dialogs.PASSING_EXIT:
      case Dialogs.WHIST_TYPE:
      case Dialogs.WHIST_ON_6_SPADES:
      case Dialogs.TRICKING_10:
      case Dialogs.MISERE_MODE:
      case Dialogs.SUIT_ORDER:
      case Dialogs.RANK_ORDER:
      case Dialogs.LOCALE:
      case Dialogs.ORIENTATION:
      case Dialogs.CONFIRM_BID:
      case Dialogs.CONFIRM_CONTRACT:
      case Dialogs.DECKS:
      case Dialogs.CLOUD_SAVE:
      case Dialogs.CARD_MOVING_MODE:
      {
        List preference = find(List.class, id);

        ((RadioListViewDialog)dialog).set(preference.getDialogTitle().toString(), preference.entriesToList(), preference.findIndexOfValue(preference.getValue()));
        break;
      }

      case Dialogs.PASSING_INTERRUPT:
      {
        ListPreference preference = find(List.class, id);

        ((CheckListViewDialog)dialog).set(preference.getDialogTitle().toString(), getResources().getStringArray(R.array.passing_interruptions), profile.settings.passingInterruptions);
        break;
      }

      case Dialogs.PROGRESS_PROFILE_UPDATING:
        ((ProgressDialog)dialog).set(R.string.please_wait, R.string.profile_updating);
        break;

      case Dialogs.CLOSE_CONFIRMATION:
        ((MessageDialog)dialog).set(R.string.warning, getString(R.string.warning_close_preferences));
        break;

      case Dialogs.INFORMATION_CLOUD_SAVE:
        ((MessageDialog)dialog).set(R.string.warning, getString(R.string.information_cloud_save));
        break;

      case Dialogs.ANIMATION_TIME:
        ((AnimationTimeDialog)dialog).set(profile.settings.animationTime);
        break;
    }
  }

  private void clearBackground(View view)
  {
    view.setBackgroundResource(0);

    if (view instanceof ViewGroup)
    {
      ViewGroup viewGroup = (ViewGroup) view;

      for (int i = 0; i < viewGroup.getChildCount(); i++)
        clearBackground(viewGroup.getChildAt(i));
    }
  }

  private void setup(Profile profile)
  {
    // remove all dialogs (except Language) to reflect locale or orientation change
    for (int id : Dialogs.set)
      removeDialog(id);

    // remove all preferences previously loaded (in case locale or orientation has been changed)
    PreferenceScreen ps = getPreferenceScreen();

    if (ps != null)
      ps.removeAll();

    // inflate preferences from xml
    addPreferencesFromResource(R.xml.preferences);

    // setup player preferences
    EditText.setup(this, Dialogs.NICKNAME, profile.nickname, profile.nickname == null ? getString(R.string.settings_default_nickname) : profile.nickname, InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES, true);

    CheckBox cb = CheckBox.setup(this, Dialogs.USE_CENTER, profile.useCenter && !profile.hacked, !profile.hacked);

    if (profile.hacked)
      cb.setSummaryOff(GUI.getColoredText("red", getString(R.string.not_allowed)));

    if (CloudManager.instance(this).isEnabled())
      List.setup(this, Dialogs.CLOUD_SAVE, R.array.cloud_save_types, profile.settings.cloudSave, Settings.CloudSave.class, entrance || profile.settings.cloudSave != Settings.CloudSave.NONE);
    else
      List.setup(this, Dialogs.CLOUD_SAVE, getString(R.string.settings_cloud_save_gms_unavailable));

    List.setup(this, Dialogs.LOCALE, R.array.locale_types, profile.settings.locale, Settings.Locale.class, entrance);
    List.setup(this, Dialogs.ORIENTATION, R.array.orientation_types, profile.settings.orientation, Settings.Orientation.class, entrance);
    DeckList.setup(this, Dialogs.DECKS, profile.settings.deck);

    // setup players levels preferences
    List.setup(this, Dialogs.LEVEL_PLAYER_LEFT, R.array.player_levels, profile.settings.levels[0], Settings.Level.class, newGame);
    List.setup(this, Dialogs.LEVEL_PLAYER_RIGHT, R.array.player_levels, profile.settings.levels[1], Settings.Level.class, newGame);

    // setup pool preferences
    List.setup(this, Dialogs.POOL_TYPE, getPoolTypesArray(profile.settings), profile.settings.gameFlavor, Settings.GameFlavor.class, newGame);
    EditText.setup(this, Dialogs.POOL_SIZE, String.valueOf(profile.settings.poolSize), String.valueOf(profile.settings.poolSize), InputType.TYPE_CLASS_NUMBER, newGame);

    if (profile.settings.locale == Settings.Locale.RUSSIAN)
    {
      PreferenceCategory category = (PreferenceCategory)findPreference("category_pool");
      CheckBox preference = find(CheckBox.class, Dialogs.USE_ORIGINAL_GAME_TYPE_NAMES);

      category.removePreference(preference);
    }
    else
      CheckBox.setup(this, Dialogs.USE_ORIGINAL_GAME_TYPE_NAMES, profile.settings.useOriginalGameTypeNames, true);

    // setup passing preferences
    List.setup(this, Dialogs.PASSING_TYPE, R.array.passing_types, profile.settings.passingType, Settings.PassingType.class, newGame);
    List.setup(this, Dialogs.PASSING_PROGRESSION, R.array.passing_progressions, profile.settings.passingProgression, Settings.PassingProgression.class, newGame);
    List.setup(this, Dialogs.PASSING_TRICK_COST, R.array.passing_trick_costs, profile.settings.passingTrickCost, Settings.PassingTrickCost.class, newGame);
    List.setup(this, Dialogs.PASSING_EXIT, R.array.passing_exits, profile.settings.passingExit, Settings.PassingExit.class, newGame);
    List.setup(this, Dialogs.PASSING_INTERRUPT, profile.settings.passingInterruptions, R.array.passing_interruptions, R.string.settings_passing_interrupt_successful_whisted_game, newGame);

    // setup whist preferences
    List.setup(this, Dialogs.WHIST_TYPE, R.array.whist_types, profile.settings.whistType, Settings.WhistType.class, newGame);
    List.setup(this, Dialogs.WHIST_ON_6_SPADES, R.array.whist_on_6_spades_types, profile.settings.whistOn6Spades, Settings.WhistOn6Spades.class, newGame);

    // setup additional conventions preferences
    List.setup(this, Dialogs.TRICKING_10, R.array.whist_tricking10_types, profile.settings.tricking10, Settings.Tricking10.class, newGame);
    CheckBox.setup(this, Dialogs.WITHOUT_3, profile.settings.without3, true);

    // setup misere preferences
    List.setup(this, Dialogs.MISERE_MODE, R.array.misere_modes, profile.settings.misereMode, Settings.MisereMode.class, true);

    // setup cards preferences
    List.setup(this, Dialogs.CARD_MOVING_MODE, R.array.card_moving_modes, profile.settings.cardMovingMode, Settings.CardMovingMode.class, true);
    List.setup(this, Dialogs.SUIT_ORDER, R.array.suit_orders, profile.settings.suitOrder, Settings.SuitOrder.class, true);
    List.setup(this, Dialogs.RANK_ORDER, R.array.rank_orders, profile.settings.rankOrder, Settings.RankOrder.class, true);
    CheckBox.setup(this, Dialogs.SUIT_SPACING, profile.settings.suitSpacing, true);

    // setup tap on round end preferences
    CheckBox.setup(this, Dialogs.ROUND_END_TAP_WHEN_NOT_PLAYING, profile.settings.roundEndTapWhenNotPlaying, true);
    CheckBox.setup(this, Dialogs.ROUND_END_TAP_WHEN_LAST_MOVER_ANDROID, profile.settings.roundEndTapWhenLastMoverAndroid, true);
    CheckBox.setup(this, Dialogs.ROUND_END_TAP_WHEN_LAST_MOVER_HUMAN, profile.settings.roundEndTapWhenLastMoverHuman, true);

    // setup confirmations
    List.setup(this, Dialogs.CONFIRM_BID, R.array.confirmation_types, profile.settings.confirmations.bid, Settings.Confirmation.class, true);
    List.setup(this, Dialogs.CONFIRM_CONTRACT, R.array.confirmation_types, profile.settings.confirmations.contract, Settings.Confirmation.class, true);

    // setup game optimizations
    CheckBox.setup(this, Dialogs.AUTOMATE_OBVIOUS_MOVES, profile.settings.automateObviousMoves, true);
    CheckBox.setup(this, Dialogs.SKIP_GAME_ON_PASS, profile.settings.skipGameOnPass, true);
    EditText.setup(this, Dialogs.ANIMATION_TIME, String.valueOf(profile.settings.animationTime), getAnimationTimeSummary(profile.settings.animationTime), InputType.TYPE_CLASS_NUMBER, true);

    // show dependencies (currently for game flavor)
    showDependencies();
  }

  private void setGameFlavorDefaults()
  {
    Profile p = pm.getCurrentProfile();

    switch (p.settings.gameFlavor)
    {
      case SOCHI:
      case LENINGRAD:
      {
        // for Sochi and Leningrad whist on 6♠ is always 'Stalingrad'
        List preference = find(List.class, Dialogs.WHIST_ON_6_SPADES);
        p.settings.whistOn6Spades = preference.update(R.array.whist_on_6_spades_types, Settings.WhistOn6Spades.MANDATORY.ordinal(), Settings.WhistOn6Spades.class);

        // for Leningrad default tricking10 type is 'CHECKED'
        if (p.settings.gameFlavor == Settings.GameFlavor.LENINGRAD)
        {
          preference = find(List.class, Dialogs.TRICKING_10);
          p.settings.tricking10 = preference.update(R.array.whist_tricking10_types, Settings.Tricking10.CHECKED.ordinal(), Settings.Tricking10.class);
        }

        // for Sochi and Leningrad passing mode following defaults are required: progression is 1,2,3,1,2,3..., tricks weight is 1 (Sochi) or 2 (Leningrad) and exit is 6,7,7,7,...
        preference = find(List.class, Dialogs.PASSING_PROGRESSION);
        p.settings.passingProgression = preference.update(R.array.passing_progressions, Settings.PassingProgression.PP_123123.ordinal(), Settings.PassingProgression.class);

        preference = find(List.class, Dialogs.PASSING_TRICK_COST);
        Settings.PassingTrickCost trickCost = p.settings.gameFlavor == Settings.GameFlavor.SOCHI ? Settings.PassingTrickCost.PTC_1 : Settings.PassingTrickCost.PTC_2;
        p.settings.passingTrickCost = preference.update(R.array.passing_trick_costs, trickCost.ordinal(), Settings.PassingTrickCost.class);

        preference = find(List.class, Dialogs.PASSING_EXIT);
        p.settings.passingExit = preference.update(R.array.passing_exits, Settings.PassingExit.PE_6777.ordinal(), Settings.PassingExit.class);
      }
      break;

      case ROSTOV:
      {
        // for Rostov whist on 6♠ is always 'Regular'
        List preference = find(List.class, Dialogs.WHIST_ON_6_SPADES);
        p.settings.whistOn6Spades = preference.update(R.array.whist_on_6_spades_types, Settings.WhistOn6Spades.ARBITRARY.ordinal(), Settings.WhistOn6Spades.class);

        // for Rostov passing mode following defaults are required: type is rotational, progression is 1,1,1,1..., tricks weight is 5 and exit is 6,6,6,6...
        preference = find(List.class, Dialogs.PASSING_TYPE);
        p.settings.passingType = preference.update(R.array.passing_types, Settings.PassingType.SLIDING.ordinal(), Settings.PassingType.class);

        preference = find(List.class, Dialogs.PASSING_PROGRESSION);
        p.settings.passingProgression = preference.update(R.array.passing_progressions, Settings.PassingProgression.PP_1111.ordinal(), Settings.PassingProgression.class);

        preference = find(List.class, Dialogs.PASSING_TRICK_COST);
        // assign dummy value for Rostov (there is no PTC_5, otherwise it will be shown for Sochi and Leningrad)
        p.settings.passingTrickCost = preference.update(R.array.passing_trick_costs, Settings.PassingTrickCost.PTC_1.ordinal(), Settings.PassingTrickCost.class);

        preference = find(List.class, Dialogs.PASSING_EXIT);
        p.settings.passingExit = preference.update(R.array.passing_exits, Settings.PassingExit.PE_6666.ordinal(), Settings.PassingExit.class);
      }
      break;
    }

    // show dependencies
    showDependencies();
  }

  private void showDependencies()
  {
    showDependencies(Dialogs.PASSING_TYPE);
    showDependencies(Dialogs.PASSING_PROGRESSION);
    showDependencies(Dialogs.PASSING_TRICK_COST);
    showDependencies(Dialogs.PASSING_EXIT);
    showDependencies(Dialogs.WHIST_ON_6_SPADES);
  }

  private void showDependencies(int dialog)
  {
    Profile p = pm.getCurrentProfile();

    ListPreference preference = find(List.class, dialog);
    preference.setEnabled(newGame && !p.settings.isRostov());

    if (dialog == Dialogs.PASSING_TRICK_COST && p.settings.isRostov())
      preference.setSummary(String.valueOf(Settings.ROSTOV_PASSING_TRICK_COST));
  }

  private String getAnimationTimeSummary(long value) {return value + " " + getString(R.string.settings_animation_time_ms);}

  private int getPoolTypesArray(Settings settings)
  {
    if (settings.locale == Settings.Locale.ENGLISH && !settings.useOriginalGameTypeNames)
      return R.array.pool_types_america;

    return R.array.pool_types;
  }

  static void initializePreferenceStyle(View view, boolean enabled)
  {
    initializePreferenceStyle(view, android.R.id.title, enabled, GUI.Color.TITLE, TITLE_TEXT_SIZE);
    initializePreferenceStyle(view, android.R.id.summary, enabled, Color.WHITE, SUMMARY_TEXT_SIZE);
  }

  private static void initializePreferenceStyle(View view, int resID, boolean enabled, int enabledColor, int textSize)
  {
    TextView tv = (TextView)view.findViewById(resID);

    tv.setTypeface(GUI.Font.NORMAL);
    tv.setTextColor(enabled ? enabledColor : GUI.Color.DISABLE);
    tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
    tv.setSingleLine(false);
    tv.setMaxLines(6);
  }

/*
  private void clear()
  {
    SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplication());

    SharedPreferences.Editor editor = preferences.edit();
    editor.clear();
    editor.commit();
  }
*/

  // device ID key
  private static final String DEVICE_ID = "deviceID";

  // title and summary text views size
  private static final int TITLE_TEXT_SIZE   = 20;
  private static final int SUMMARY_TEXT_SIZE = 16;

  // player name size limits
  private final static int MIN_PLAYER_NAME_SIZE = 1;
  private final static int MAX_PLAYER_NAME_SIZE = 32;

  // pool size thresholds
  private final static int MIN_POOL_SIZE = 1;
  private final static int MAX_POOL_SIZE = 99;

  private static class Dialogs
  {
    // preference dialogs
    private static final int NICKNAME     = 1;
    private static final int LOCALE       = 2;
    private static final int ORIENTATION  = 3;
    private static final int USE_CENTER   = 4;
    private static final int CLOUD_SAVE   = 5;
    private static final int DECKS        = 6;

    private static final int LEVEL_PLAYER_LEFT = 7;
    private static final int LEVEL_PLAYER_RIGHT = 8;

    private static final int POOL_TYPE    = 9;
    private static final int POOL_SIZE    = 10;
    private static final int USE_ORIGINAL_GAME_TYPE_NAMES = 11;

    private static final int PASSING_TYPE = 12;
    private static final int PASSING_PROGRESSION  = 13;
    private static final int PASSING_TRICK_COST   = 14;
    private static final int PASSING_EXIT = 15;
    private static final int PASSING_INTERRUPT = 16;

    private static final int WHIST_TYPE   = 17;
    private static final int WHIST_ON_6_SPADES = 18;

    private static final int TRICKING_10 = 19;
    private static final int WITHOUT_3   = 20;

    private static final int MISERE_MODE  = 21;

    private static final int CARD_MOVING_MODE = 22;
    private static final int SUIT_ORDER   = 23;
    private static final int RANK_ORDER   = 24;
    private static final int SUIT_SPACING = 25;

    private static final int ROUND_END_TAP_WHEN_NOT_PLAYING = 26;
    private static final int ROUND_END_TAP_WHEN_LAST_MOVER_ANDROID = 27;
    private static final int ROUND_END_TAP_WHEN_LAST_MOVER_HUMAN = 28;

    private static final int CONFIRM_BID = 29;
    private static final int CONFIRM_CONTRACT = 30;

    private static final int AUTOMATE_OBVIOUS_MOVES = 31;
    private static final int SKIP_GAME_ON_PASS = 32;
    private static final int ANIMATION_TIME = 33;

    // application dialogs
    private static final int PROGRESS_PROFILE_UPDATING = 100;
    private static final int CLOSE_CONFIRMATION = 101;
    private static final int INFORMATION_CLOUD_SAVE = 102;

    // all dialogs id's set
    private static final int set[] = new int[] {
        NICKNAME, CLOUD_SAVE, DECKS, POOL_TYPE, POOL_SIZE, PASSING_TYPE, PASSING_PROGRESSION, PASSING_TRICK_COST,
        PASSING_EXIT, WHIST_TYPE, WHIST_ON_6_SPADES, TRICKING_10, CARD_MOVING_MODE, RANK_ORDER, SUIT_ORDER, PASSING_INTERRUPT,
        PROGRESS_PROFILE_UPDATING, CLOSE_CONFIRMATION, LEVEL_PLAYER_LEFT, LEVEL_PLAYER_RIGHT, CONFIRM_BID, CONFIRM_CONTRACT, ANIMATION_TIME
    };
  }

  // is it a new game
  private boolean newGame;
  // is this activity opened from entrance
  private boolean entrance;
  // profile manager instance
  private ProfileManager pm;
}
